package org.jflame.web.spring;

import org.jflame.commons.model.BaseResult;
import org.jflame.commons.model.CallResult;

import java.util.Arrays;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.http.converter.json.AbstractJsonHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * json返回统一封装为CallResult
 *
 * @author charles.zhang
 */
@ControllerAdvice
public class RestResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private String[] supportedClassNames = { "com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter",
            "com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter" };

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (BaseResult.class.isAssignableFrom(returnType.getParameterType())
                || ResponseEntity.class.isAssignableFrom(returnType.getParameterType())) {
            return false;
        }
        if (AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType)
                || AbstractJsonHttpMessageConverter.class.isAssignableFrom(converterType)) {
            return true;
        }
        // 非spring内置converter使用类名判断.
        return ArrayUtils.contains(supportedClassNames, converterType.getName());
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
            Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
            ServerHttpResponse response) {
        if (!(body instanceof BaseResult)) {
            return CallResult.ok(body);
        }
        return body;
    }

    /**
     * 添加支持的converter类名, 默认只支持实现了AbstractJsonHttpMessageConverter和AbstractJackson2HttpMessageConverter的类,以及
     * FastJsonHttpMessageConverter
     *
     * @param supportedClassNames
     */
    public void addSupportedConverter(String... supportedClassNames) {
        if (ArrayUtils.isEmpty(supportedClassNames)) {
            return;
        }
        this.supportedClassNames = ArrayUtils.addAll(supportedClassNames);
    }

    public void addSupportedConverter(Class<?>... supportedClasses) {
        if (ArrayUtils.isEmpty(supportedClasses)) {
            return;
        }
        Arrays.stream(supportedClasses)
                .forEach(s ->
                {
                    this.supportedClassNames = ArrayUtils.add(supportedClassNames, s.getName());
                });

    }
}
